package com.dotndot.controller.network;

import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.ByteArrayBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.message.BasicNameValuePair;

import android.graphics.Bitmap;
import android.os.Handler;
import android.os.Message;

import com.dotndot.controller.Server.ReceiveServerParam;
import com.dotndot.controller.Server.SendServerParam;
import com.dotndot.controller.network.data.ReqNetworkData;
import com.dotndot.controller.network.data.RespNetworkData;
import com.dotndot.controller.network.define.INetwork;
import com.dotndot.controller.network.define.INetworkAPI.BABY;
import com.dotndot.controller.network.define.INetworkAPI.JOIN;
import com.dotndot.controller.network.define.INetworkAPI.LOGIN;
import com.dotndot.controller.network.define.INetworkAPI.REQUEST;
import com.dotndot.controller.network.define.INetworkAPI.REQUEST_TYPE;
import com.dotndot.controller.network.define.INetworkAPI.STORY;
import com.dotndot.controller.network.define.INetworkAPI.STORYLIST;
import com.dotndot.controller.network.define.INetworkAPI.VERSION;
import com.dotndot.controller.utils.Utils;

public class NetworkManager implements INetwork
{
    private final int RET_NETWORK_MANAGER = 0;

    public void requestServer( Handler handler, SendServerParam param )
    {
        requestNetwork(handler, param);
    }

    private REQUEST_TYPE getApiType( REQUEST api )
    {
        switch( api )
        {
            case BABY_ADD_API:                
            case STORY_ADD_API:
                return REQUEST_TYPE.MULTIPART_POST_TYPE;

            default:
                return REQUEST_TYPE.NORMAL_POST_TYPE;
        }
    }

    private String getServerUri( REQUEST api )
    {
        String uri = new String();
        switch( api )
        {
            case VERSION_API:
                uri = makeServerUri(VERSION_URI);
                break;

            case LOGIN_API:
                uri = makeServerUri(LOGIN_URI);
                break;

            case JOIN_API:
                uri = makeServerUri(JOIN_URI);
                break;

            case BABY_ADD_API:
                uri = makeServerUri(BABY_ADD_URI);
                break;
                
            case BABY_LIST_API:
                uri = makeServerUri(BABY_LIST_URI);
                break;
                
            case STORY_ADD_API:
                uri = makeServerUri(STORY_ADD_URI);
                break;

            case STORY_LIST_API:
                uri = makeServerUri(STORY_LIST_URI);
                break;
                
            case DIARY_ADD_API:
                uri = makeServerUri(DIARY_ADD_URI);
                break;
                
            case DIARY_LIST_API:
                uri = makeServerUri(DIARY_LIST_URI);
                break;
        }
        return uri;
    }

    private String makeServerUri( String uri )
    {
        return MAIN_SERVER_URI + uri;
    }

    private List<BasicNameValuePair> setNormalPostParam( SendServerParam param )
    {
        List<BasicNameValuePair> mBasicParam = new ArrayList<BasicNameValuePair>();

        switch( param.getApi() )
        {
            case VERSION_API:
                mBasicParam.add(new BasicNameValuePair(VERSION.appVersion.name(), param.get(VERSION.appVersion)));
                mBasicParam.add(new BasicNameValuePair(VERSION.deviceOS.name(), param.get(VERSION.deviceOS)));
                mBasicParam.add(new BasicNameValuePair(VERSION.deviceID.name(), param.get(VERSION.deviceID)));
                break;

            case LOGIN_API:
                mBasicParam.add(new BasicNameValuePair(LOGIN.email.name(), param.get(LOGIN.email)));
                mBasicParam.add(new BasicNameValuePair(LOGIN.password.name(), param.get(LOGIN.password)));
                break;

            case JOIN_API:
                mBasicParam.add(new BasicNameValuePair(JOIN.email.name(), param.get(JOIN.email)));
                mBasicParam.add(new BasicNameValuePair(JOIN.password.name(), param.get(JOIN.password)));
                mBasicParam.add(new BasicNameValuePair(JOIN.gender.name(), param.get(JOIN.gender)));
                mBasicParam.add(new BasicNameValuePair(JOIN.nickname.name(), param.get(JOIN.nickname)));
                mBasicParam.add(new BasicNameValuePair(JOIN.birthday.name(), param.get(JOIN.birthday)));
                mBasicParam.add(new BasicNameValuePair(JOIN.terms.name(), param.get(JOIN.terms)));
                break;

            case BABY_LIST_API:
                mBasicParam.add(new BasicNameValuePair(BABY.momIndex.name(), param.get(BABY.momIndex)));
                break;
                
            case STORY_LIST_API:
                mBasicParam.add(new BasicNameValuePair(STORYLIST.userIndex.name(), param.get(STORYLIST.userIndex)));
                mBasicParam.add(new BasicNameValuePair(STORYLIST.viewType.name(), param.get(STORYLIST.viewType)));
                mBasicParam.add(new BasicNameValuePair(STORYLIST.viewPage.name(), param.get(STORYLIST.viewPage)));
                break;
                
            case DIARY_ADD_API:
                mBasicParam.add(new BasicNameValuePair("test", "test11"));
                break;
                
            case DIARY_LIST_API:
                mBasicParam.add(new BasicNameValuePair("test", "test11"));
                break;
        }

        return mBasicParam;
    }

    private MultipartEntity setMultipartPostParam( SendServerParam param ) throws UnsupportedEncodingException
    {
        MultipartEntity mMultipartParam = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);

        switch( param.getApi() )
        {
            case STORY_ADD_API:
                mMultipartParam.addPart(STORY.userIndex.name(), new StringBody(param.get(STORY.userIndex), "text/plain", Charset.forName("UTF-8")));

                if( param.get(STORY.content) != null )
                {
                    mMultipartParam.addPart(STORY.content.name(), new StringBody(param.get(STORY.content), "text/plain", Charset.forName("UTF-8")));
                }

                if( param.getBitmap(STORY.image) != null )
                {
                    Bitmap bitmap = param.getBitmap(STORY.image);
                    ByteArrayBody byteArrayBody = Utils.getInstance().byteArrayBodyToImage(bitmap);
                    mMultipartParam.addPart(STORY.image.name(), byteArrayBody);
                }
                
                mMultipartParam.addPart(STORY.viewType.name(), new StringBody(param.get(STORY.viewType), "text/plain", Charset.forName("UTF-8")));
                break;
                
            case BABY_ADD_API:
                mMultipartParam.addPart(BABY.momIndex.name(), new StringBody(param.get(BABY.momIndex), "text/plain", Charset.forName("UTF-8")));
                mMultipartParam.addPart(BABY.name.name(), new StringBody(param.get(BABY.name), "text/plain", Charset.forName("UTF-8")));
                mMultipartParam.addPart(BABY.gender.name(), new StringBody(param.get(BABY.gender), "text/plain", Charset.forName("UTF-8")));
                mMultipartParam.addPart(BABY.birthday.name(), new StringBody(param.get(BABY.birthday), "text/plain", Charset.forName("UTF-8")));

                if( param.getBitmap(BABY.avatar) != null )
                {
                    Bitmap bitmap = param.getBitmap(BABY.avatar);
                    ByteArrayBody byteArrayBody = Utils.getInstance().byteArrayBodyToImage(bitmap);
                    mMultipartParam.addPart(BABY.avatar.name(), byteArrayBody);
                }
                break;
        }

        return mMultipartParam;
    }

    private void requestNetwork( Handler handler, SendServerParam param )
    {

        try
        {
            switch( getApiType(param.getApi()) )
            {
                case NORMAL_POST_TYPE:
                    sendNormalPost(handler, param);
                    break;

                case MULTIPART_POST_TYPE:
                    sendMultipartPost(handler, param);
                    break;
            }
        }
        catch( UnsupportedEncodingException e )
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    private void sendNormalPost( Handler handler, SendServerParam param )
    {
        Object data = null;
        String uri = getServerUri(param.getApi());
        data = setNormalPostParam(param);

        ReqNetworkData reqData = new ReqNetworkData();
        reqData.setAPI(param.getApi());
        reqData.setType(getApiType(param.getApi()));
        reqData.setActivityHandler(handler);
        reqData.setManagerHandler(mNetworkManagerHandler);
        reqData.setURI(uri);
        reqData.setDATA(data);
        new NetworkThread(reqData);

    }

    private void sendMultipartPost( Handler handler, SendServerParam param ) throws UnsupportedEncodingException
    {
        Object data = null;
        String uri = getServerUri(param.getApi());
        data = setMultipartPostParam(param);

        ReqNetworkData reqData = new ReqNetworkData();
        reqData.setAPI(param.getApi());
        reqData.setType(getApiType(param.getApi()));
        reqData.setManagerHandler(mNetworkManagerHandler);
        reqData.setActivityHandler(handler);
        reqData.setURI(uri);
        reqData.setDATA(data);
        new NetworkThread(reqData);
    }

    private Handler mNetworkManagerHandler = new Handler()
    {
        @Override
        public void handleMessage( Message msg )
        {
            RespNetworkData postData = null;
            if( msg.obj instanceof RespNetworkData )
            {
                postData = (RespNetworkData) msg.obj;

                ReceiveServerParam mRespData = new ReceiveServerParam();
                mRespData.setAPI(postData.getAPI());
                mRespData.setERR(postData.getERR());
                mRespData.setDATA(postData.getData());
                Message message = postData.getHandler().obtainMessage(RET_NETWORK_MANAGER, mRespData);
                postData.getHandler().sendMessage(message);
            }
        }

    };
}
